﻿using System.Collections.Generic;
using System.Threading.Tasks;
using PCLStorage;
using Newtonsoft.Json;

namespace Moven.Data
{
    class LocalKeyValueStorage : IKeyValueStorage
    {
        Dictionary<string, object> _cache = new Dictionary<string, object>();
        IFolder _folder;

        async Task<bool> IsFileExistsAsync(string path) =>
            await _folder.CheckExistsAsync(path) ==
                ExistenceCheckResult.FileExists;

        public LocalKeyValueStorage(IFolder folder = null)
        {
            _folder = folder != null ? folder : SpecialFolder.Current.Local;

			foreach(var pair in PredefinedData.Data)
            {
				var fileName = pair.Key.AddJsonExtension();
				if (!IsFileExistsAsync(fileName).Result)
				{
					var file = _folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting).Result;
					file.WriteAllTextAsync(pair.Value).Wait();
				}
            }
        }

        public T GetValue<T>(string key) => GetValueAsync<T>(key).Result;

        public async Task<T> GetValueAsync<T>(string key)
        {
            if (_cache.ContainsKey(key))
            {
                return (T)_cache[key];
            }
			var fileName = key.AddJsonExtension();

            if (await IsFileExistsAsync(fileName))
            {
                var file = await _folder.GetFileAsync(fileName);
                var text = await file.ReadAllTextAsync();
                var value = JsonConvert.DeserializeObject<T>(text);
                _cache.Add(key, value);
                return value;
            }
            _cache.Add(key, default(T));
            return default(T);
        }

        public T GetValueFromPredefinedData<T>(string key)
        {
			if (!PredefinedData.Data.ContainsKey(key))
            {
                return default(T);
            }

            return JsonConvert.DeserializeObject<T>(PredefinedData.Data[key]);
        }

        public void SetValue<T>(string key, T value)
        {
            SetValueAsync(key, value).Wait();
        }

        public async Task SetValueAsync<T>(string key, T value)
        {
            _cache[key] = value;
			if (ArticlesStore.IsArticlesRefreshTest && key == ArticlesStore.ArticlesKey)
			{
				return;
			}
			var fileName = key.AddJsonExtension();
            IFile file = null;
            if (!await IsFileExistsAsync(fileName))
            {
                file = await _folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
            }
            else
            {
                file = await _folder.GetFileAsync(fileName);
            }
            var json = JsonConvert.SerializeObject(value);
            await file.WriteAllTextAsync(json);
        }
    }
}
